/**
 * @Copyright ®2015 Sinosoft Co. Ltd. All rights reserved.<br/>
 * 项目名称 : 中科软支付平台
 * 创建日期 : 2016年12月13日
 * 修改历史 : 
 *     1. [2016年12月13日]创建文件 by liuyujia
 */
package com.sinosoft.sinopay.web.weixinpay.biz.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sinosoft.sinocloud.common.biz.service.ReportLogService;
import com.sinosoft.sinocloud.platform.base.SinoBaseService;
import com.sinosoft.sinocloud.platform.common.exception.biz.IllegalRequestException;
import com.sinosoft.sinocloud.platform.common.exception.biz.SinoBizException;
import com.sinosoft.sinocloud.platform.common.exception.checked.RepeatRequestException;
import com.sinosoft.sinocloud.platform.common.exception.system.SinoSystemException;
import com.sinosoft.sinocloud.platform.common.util.DateUtil;
import com.sinosoft.sinocloud.platform.common.util.PersonIDUtil;
import com.sinosoft.sinopay.api.common.dto.pay.PaymentInfoDetailDTO;
import com.sinosoft.sinopay.api.common.dto.query.PayInfoQryParam;
import com.sinosoft.sinopay.customer.facade.CustomerFacadeService;
import com.sinosoft.sinopay.merchants.facade.MerchantInfoFacadeService;
import com.sinosoft.sinopay.payrules.config.ENUM_IP_BIZTYPE;
import com.sinosoft.sinopay.payrules.config.ENUM_IP_SECURITYLIST;
import com.sinosoft.sinopay.payrules.dto.MerchantCheckDTO;
import com.sinosoft.sinopay.payrules.facade.PayRuleFacade;
import com.sinosoft.sinopay.payrules.facade.SecurityListFacadeService;
import com.sinosoft.sinopay.paytrade.config.ENUM_PAY_STATUS;
import com.sinosoft.sinopay.paytrade.facade.PaymentTradeQueryFacadeService;
import com.sinosoft.sinopay.web.util.AmountTransUtil;
import com.sinosoft.sinopay.web.util.WechatSignUtil;
import com.sinosoft.sinopay.web.weixinpay.biz.service.WechatSecurityService;
import com.sinosoft.sinopay.web.weixinpay.dto.WechatEntryRequsetDTO;

/**  
 * 【微信支付安全服务接口实现类】
 * @author liuyujia
 * @date 2016年12月13日 下午5:20:28 
 * @version V1.0  
 */
@Service
public class WechatSecurityServiceImpl extends SinoBaseService implements WechatSecurityService{
	 @Autowired
	 private MerchantInfoFacadeService merchantSecurityFacadeService;
	 @Autowired
	 private SecurityListFacadeService securityListFacadeService;
	 @Autowired
	 private PaymentTradeQueryFacadeService paymentTradeQueryFacadeService;
	 @Autowired
	 private CustomerFacadeService customerFacadeService;
	 @Autowired
	 private PayRuleFacade payRuleFacade;
	 @Autowired
     private ReportLogService reportLogService;
	 
	/** 商户签名信息缓存map */
	 private Map<String, String> signKeysMap;
	 /** IP白名单缓存 */
	 private List<String> ipWhiteList;
	 /** IP黑名单缓存 */
	 private List<String> ipBlackList;
	 
	@Override
	public void checkMerchantSignValid(String merchantCode, WechatEntryRequsetDTO tWechatEntryRequsetDTO, String signMsg) {
		if(signKeysMap==null || signKeysMap.size()==0){
			 //获取全部的商户签名信息
			 signKeysMap = merchantSecurityFacadeService.getAllMerchantSignKeys();
		 }
		//获取商户对应的key值
		if(signKeysMap.get(merchantCode)==null){
			throw new IllegalRequestException("商户不存在");
		}
		String tSignKey = signKeysMap.get(merchantCode);
		//封装签名参数
		 Map<String,String> tSignInfoMap = new HashMap<String,String>();
		 tSignInfoMap.put("merchantCode",merchantCode);
         tSignInfoMap.put("bizNo", tWechatEntryRequsetDTO.getBizNo());
         tSignInfoMap.put("bizType", tWechatEntryRequsetDTO.getBizType());
         tSignInfoMap.put("transType", tWechatEntryRequsetDTO.getTransType());
         tSignInfoMap.put("transDesc", tWechatEntryRequsetDTO.getTransDesc());
         tSignInfoMap.put("serialNo", tWechatEntryRequsetDTO.getSerialNo());
         tSignInfoMap.put("accountName", tWechatEntryRequsetDTO.getAccountName());
         tSignInfoMap.put("accountGender", tWechatEntryRequsetDTO.getAccountGender());
         Date tAccountBirthday = tWechatEntryRequsetDTO.getAccountBirthday();
         String birthday = DateUtil.getDateStr(tAccountBirthday, "yyyy-MM-dd");
         tSignInfoMap.put("accountBirthday", birthday);
         tSignInfoMap.put("idType", tWechatEntryRequsetDTO.getIdType());
         tSignInfoMap.put("idNo", tWechatEntryRequsetDTO.getIdNo());
         if(tWechatEntryRequsetDTO.getPayAmount()==null || tWechatEntryRequsetDTO.getPayAmount().equals(0)){
        	 throw new IllegalRequestException("金额不能为空");
         }
         AmountTransUtil aAmountTransUtil = new AmountTransUtil();
         String tPayAmount = aAmountTransUtil.transAmount(tWechatEntryRequsetDTO.getPayAmount());
         tSignInfoMap.put("payAmount",tPayAmount);//金额转换成分
         Date tRequestDate = tWechatEntryRequsetDTO.getRequestDate();
         String date = DateUtil.getDateStr(tRequestDate, "yyyy-MM-dd");
         tSignInfoMap.put("requestDate",date);
         tSignInfoMap.put("remark",tWechatEntryRequsetDTO.getRemark());
         String A = tSignInfoMap.toString();
         String tCompareSignMsg = WechatSignUtil.encryMD5(tSignInfoMap,tSignKey);
         if(signMsg ==null || !signMsg.equals(tCompareSignMsg)){
             throw new IllegalRequestException("签名不合法");
         }
	}

	@Override
	public void checkRequestIpValid(String tRequestIp) throws IllegalRequestException {
		//TODO
		securityListFacadeService.checkIpValid(tRequestIp, ENUM_IP_BIZTYPE.GATEWAY, ENUM_IP_SECURITYLIST.BLACK);		
	}

	@Override
	public void checkRepeatRequest(String merchantCode, String serialNo) throws RepeatRequestException {
		if(serialNo==null || serialNo==""){
			throw new RepeatRequestException("交易流水号不能为空");
		}
		reportLogService.checkRepeatRequest(merchantCode,serialNo);
	}

	@Override
	public void checkPayNoSignValid(String PayNo, String PayWay, String SignMsg) throws IllegalRequestException {
		logger.info("微信支付授权回调验证签名开始......");
		PayInfoQryParam tPayInfoQryParam = new PayInfoQryParam();
		tPayInfoQryParam.setPayNo(PayNo);
		tPayInfoQryParam.setPayType(PayWay);
		PaymentInfoDetailDTO tPaymentInfoDetailDTO = paymentTradeQueryFacadeService.queryPaymentOrderByPayNo(PayNo);
		if(tPaymentInfoDetailDTO==null){
			throw new IllegalRequestException("支付订单号有误, 订单号为" + PayNo);
		}
		//封装签名参数
		Map<String,String> tSignInfoMap = new HashMap<String,String>();
		tSignInfoMap.put("merchantCode",tPaymentInfoDetailDTO.getMerchantCode());
        tSignInfoMap.put("bizNo", tPaymentInfoDetailDTO.getBizNo());
        tSignInfoMap.put("bizType", tPaymentInfoDetailDTO.getBizType());
        tSignInfoMap.put("transDesc", tPaymentInfoDetailDTO.getTradeDesc());
        tSignInfoMap.put("serialNo", tPaymentInfoDetailDTO.getSerialNo());
        tSignInfoMap.put("accountName", tPaymentInfoDetailDTO.getAccountName());
        tSignInfoMap.put("idType", tPaymentInfoDetailDTO.getIdType());
        String idNo = tPaymentInfoDetailDTO.getIdNo();
        tSignInfoMap.put("idNo", idNo);
        if(tPaymentInfoDetailDTO.getIdType()!=null && "1".equals(tPaymentInfoDetailDTO.getIdType())){
	        tSignInfoMap.put("accountGender", getGenderByIdCard(idNo));
	        Date tAccountBirthday = DateUtil.parseDate(PersonIDUtil.getBirthByIdCard(idNo), "yyyyMMdd");
	        String birthday = DateUtil.getDateStr(tAccountBirthday, "yyyy-MM-dd");
	        tSignInfoMap.put("accountBirthday", birthday);
        }
        else{
        	tSignInfoMap.put("accountGender", "");
        	tSignInfoMap.put("accountBirthday", "");
        }
        if(tPaymentInfoDetailDTO.getPayAmount()==null || tPaymentInfoDetailDTO.getPayAmount().equals(0)){
       	 	throw new IllegalRequestException("金额不能为空");
        }
        AmountTransUtil aAmountTransUtil = new AmountTransUtil();
        String tPayAmount = aAmountTransUtil.transAmount(tPaymentInfoDetailDTO.getPayAmount());
        tSignInfoMap.put("payAmount",tPayAmount);//金额转换成分
        Date tRequestDate = tPaymentInfoDetailDTO.getCreateDate();
        String date = DateUtil.getDateStr(tRequestDate, "yyyy-MM-dd");
        tSignInfoMap.put("requestDate", date);
        tSignInfoMap.put("remark", PayNo);
        if(signKeysMap==null || signKeysMap.size()==0){
			 //获取全部的商户签名信息
			 signKeysMap = merchantSecurityFacadeService.getAllMerchantSignKeys();
		 }
		//获取商户对应的key值
		if(signKeysMap.get(tPaymentInfoDetailDTO.getMerchantCode())==null){
			throw new IllegalRequestException("商户不存在");
		}
		String tSignKey = signKeysMap.get(tPaymentInfoDetailDTO.getMerchantCode());
		logger.info("授权验签信息为:"+tSignInfoMap);
		String tCompareSignMsg = WechatSignUtil.encryMD5(tSignInfoMap,tSignKey);
		logger.info("签名信息:"+tCompareSignMsg);
        if(SignMsg ==null || !SignMsg.equals(tCompareSignMsg)){
            throw new IllegalRequestException("签名不合法");
        }
	}

	@Override
	public void checkCustomerByOpenid(String openid, PaymentInfoDetailDTO pPaymentInfoDetailDTO) throws IllegalRequestException {
		// TODO Auto-generated method stub
		//客户信息查询
//		customerFacadeService.saveCustomerPayAccountInfo(payInfoDTO)
		//pPaymentInfoDetailDTO里获取五要素
		//五要素进行对比
	}

	@Override
	public void checkMerchantRules(MerchantCheckDTO merchantCheckDTO) throws SinoBizException, SinoSystemException{
		payRuleFacade.checkMerchant(merchantCheckDTO);
		
	}

	@Override
	public void checkPayStatus(String payNo) throws IllegalRequestException {
		logger.info("判断支付订单号支付状态stsrt......");
		PayInfoQryParam tPayInfoQryParam = new PayInfoQryParam();
		tPayInfoQryParam.setPayNo(payNo);
		PaymentInfoDetailDTO tPaymentInfoDetailDTO = paymentTradeQueryFacadeService.queryPaymentOrderByPayNo(payNo);
		if(tPaymentInfoDetailDTO==null ){
			throw new IllegalRequestException("支付订单号有误,订单号为" + payNo);
		}
		if(tPaymentInfoDetailDTO.getPayState().equals(ENUM_PAY_STATUS.PAY_PAYED.code())){
			throw new IllegalRequestException("支付订单号不可重复支付");
		}
	}
	
	public static String getGenderByIdCard(String idCard) {
		String sGender = "未知";

		String sCardNum = idCard.substring(16, 17);
		if (Integer.parseInt(sCardNum) % 2 != 0)
			sGender = "M";
		else {
			sGender = "F";
		}
		return sGender;
	}
}
